import pika
import threading
from typing import Optional
from squirrel_core.commons.utils.get_config import get_config


class MQConnectionSingleton:
    _instance = None
    _lock = threading.Lock()
    mq_host = get_config(sections="base").get("mq_host", "")
    mq_port = get_config(sections="base").get("mq_port", "")
    mq_user = get_config(sections="base").get("mq_user", "")
    mq_pwd = get_config(sections="base").get("mq_pwd", "")

    def __init__(self):
        if not hasattr(self, '_initialized'):
            self._connection: Optional[pika.BlockingConnection] = None
            self._channel: Optional[pika.adapters.blocking_connection.BlockingChannel] = None
            self._connection_params = None
            self._initialized = True

    @classmethod
    def get_instance(cls):
        if cls._instance is None:
            with cls._lock:
                if cls._instance is None:
                    cls._instance = cls()
        return cls._instance

    def initialize_connection(self, host=mq_host, port=mq_port, username=mq_user,
                              password=mq_pwd, virtual_host='/', **kwargs):
        if self._connection_params is None:
            self._connection_params = pika.ConnectionParameters(
                host=host,
                port=port,
                credentials=pika.PlainCredentials(username, password),
                virtual_host=virtual_host,
                **kwargs
            )

    def get_connection(self) -> pika.BlockingConnection:
        with self._lock:
            if self._connection is None or self._connection.is_closed:
                if self._connection_params is None:
                    self.initialize_connection()

                self._connection = pika.BlockingConnection(self._connection_params)
                print("MQ连接已建立")

            return self._connection

    def get_channel(self) -> pika.adapters.blocking_connection.BlockingChannel:
        connection = self.get_connection()
        if self._channel is None or self._channel.is_closed:
            self._channel = connection.channel()
        return self._channel

    def declare_queue(self, queue_name: str, durable=False, exclusive=False,
                      auto_delete=False, arguments=None):
        """声明队列"""
        channel = self.get_channel()
        channel.queue_declare(
            queue=queue_name,
            durable=durable,
            exclusive=exclusive,
            auto_delete=auto_delete,
            arguments=arguments
        )
        return queue_name

    def send_message(self, queue_name: str, message: str, **kwargs):
        channel = self.get_channel()
        with self._lock:
            try:
                channel.basic_publish(
                    exchange='',
                    routing_key=queue_name,
                    body=message,
                    properties=pika.BasicProperties(
                        delivery_mode=2,
                    )
                )
                print(f"消息已发送到队列 '{queue_name}'")
            except Exception as e:
                print(f"发送消息到队列 '{queue_name}' 失败: {e}")

    def close_connection(self):
        with self._lock:
            if self._channel and not self._channel.is_closed:
                self._channel.close()
            if self._connection and not self._connection.is_closed:
                self._connection.close()
            self._channel = None
            self._connection = None
            print("MQ连接已关闭")
